package com.yc.system.service.impl;

import com.yc.common.constant.MenuConstants;
import com.yc.common.core.domain.entity.SysMenu;
import com.yc.common.core.domain.entity.SysRole;
import com.yc.common.utils.StringUtil;
import com.yc.system.domain.vo.MetaVo;
import com.yc.system.domain.vo.RouterVo;
import com.yc.system.mapper.SysMenuMapper;
import com.yc.system.mapper.SysRoleMapper;
import com.yc.system.service.ISysMenuService;
import com.yc.system.service.ISysUserRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 菜单服务实现
 *
 * @Author YanChen
 * @Date 2025/4/13 13:49
 **/
@Service
public class SysMenuServiceImpl implements ISysMenuService {

    @Autowired
    private SysMenuMapper menuMapper;

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private ISysUserRoleService userRoleService;

    /**
     * 根据角色ID查询菜单
     *
     * @param roleId 角色ID（可为null）
     * @return 有效的菜单列表（无null项），若角色无效或未关联菜单则返回空列表
     */
    @Override
    public List<SysMenu> selectMenusByRoleId(Long roleId) {
        // 初始化结果集
        List<SysMenu> menus = new ArrayList<>();

        // 处理无效角色ID
        if (roleId == null) {
            return menus;
        }

        // 管理员获取所有菜单，非管理员获取关联菜单
        if (isAdminRole(roleId)) {
            menus = menuMapper.selectList(null);
        } else {
            menus = menuMapper.selectMenusByRoleId(roleId);
        }

        // 过滤无效菜单项（防御性编程）
        return menus.stream()
                .filter(menu -> menu != null && menu.getId() != null)
                .collect(Collectors.toList());
    }

    /**
     * 判断是否为管理员角色
     */
    private boolean isAdminRole(Long roleId) {
        SysRole sysRole = roleMapper.selectByPrimaryKey(roleId);
        return sysRole != null && sysRole.getIsAdmin() == MenuConstants.IS_ADMIN;
    }

    /**
     * 构建前端路由所需要的菜单
     */
    @Override
    public List<RouterVo> buildRouters(List<SysMenu> menus) {
        // 防御性编程
        if (menus == null || menus.isEmpty()) {
            return new ArrayList<>();
        }

        // 按 parentId 分组，减少嵌套遍历
        Map<Long, List<SysMenu>> menuGroup = menus.stream()
                .filter(menu -> menu != null && menu.getParentId() != null)
                .collect(Collectors.groupingBy(SysMenu::getParentId));

        // 构建顶级菜单（parentId=0）
        return menuGroup.getOrDefault(MenuConstants.ROOT_MENU_ID, Collections.emptyList()).stream()
                .sorted(Comparator.comparing(menu -> menu.getOrderNum() != null ? menu.getOrderNum() : 0))
                .map(menu -> buildRouter(menu, menuGroup))
                .collect(Collectors.toList());
    }

    /**
     * 构建单个路由对象
     */
    private RouterVo buildRouter(SysMenu menu, Map<Long, List<SysMenu>> menuGroup) {
        RouterVo router = new RouterVo();
        router.setHidden(MenuConstants.HIDDEN.equals(menu.getVisible()));
        router.setName(getRouterName(menu));
        router.setPath(getRouterPath(menu));
        router.setComponent(getComponent(menu));

        // 设置元数据
        MetaVo meta = new MetaVo();
        meta.setTitle(menu.getMenuName());
        meta.setIcon(menu.getIcon());
        meta.setNoCache(MenuConstants.NO_CACHE.equals(menu.getIsCache()));
        router.setMeta(meta);

        // 处理外链
        if (menu.getIsFrame() == MenuConstants.FRAME_YES && StringUtil.isNotEmpty(menu.getPath())
                && menu.getPath().startsWith(MenuConstants.HTTP)) {
            router.setComponent(MenuConstants.INNER_LINK);
            meta.setLink(menu.getPath());
            router.setPath(MenuConstants.INNER_LINK_PATH);
        }

        // 当存在子节点时，设置重定向
        List<SysMenu> childMenus = menuGroup.getOrDefault(menu.getId(), Collections.emptyList());
        if (!childMenus.isEmpty() && MenuConstants.TYPE_DIR.equals(menu.getMenuType())) {
            router.setAlwaysShow(true);
            // 如果父节点是目录，设置重定向到第一个子菜单
            if (!childMenus.isEmpty()) {
                SysMenu firstChild = childMenus.stream()
                        .sorted(Comparator.comparing(m -> m.getOrderNum() != null ? m.getOrderNum() : 0))
                        .findFirst()
                        .orElse(null);

                if (firstChild != null) {
                    router.setRedirect(router.getPath() + "/" + firstChild.getPath());
                }
            }
        }

        // 递归构建子菜单
        if (!childMenus.isEmpty()) {
            List<RouterVo> children = childMenus.stream()
                    .sorted(Comparator.comparing(m -> m.getOrderNum() != null ? m.getOrderNum() : 0))
                    .map(child -> buildRouter(child, menuGroup))
                    .collect(Collectors.toList());
            router.setChildren(children);
        }

        return router;
    }

    /**
     * 获取用户菜单列表
     */
    @Override
    public List<RouterVo> getUserMenuList(Long userId) {
        if (userId == null) {
            return new ArrayList<>();
        }

        // 查询当前用户的角色ID集合
        List<Long> roleIds = userRoleService.getRoleIdsByUserId(userId);
        if (roleIds == null || roleIds.isEmpty()) {
            return new ArrayList<>();
        }

        // 收集所有角色下的菜单信息 - 使用Set避免重复
        Set<SysMenu> menuSet = new HashSet<>();
        for (Long roleId : roleIds) {
            List<SysMenu> roleMenus = selectMenusByRoleId(roleId);
            if (roleMenus != null) {
                menuSet.addAll(roleMenus);
            }
        }

        // 排除按钮类型的菜单，转为List
        List<SysMenu> menuList = menuSet.stream()
                .filter(menu -> menu != null && !MenuConstants.TYPE_BUTTON.equals(menu.getMenuType()))
                .collect(Collectors.toList());

        // 构建前端路由数据
        return buildRouters(menuList);
    }

    /**
     * 获取路由名称
     */
    private String getRouterName(SysMenu menu) {
        if (menu == null) {
            return MenuConstants.DEFAULT_MENU_NAME;
        }

        String routerName = StringUtil.capitalize(menu.getMenuName());
        // 非外链且不是一级目录（类型为目录的顶级菜单）
        if (menu.getIsFrame() == MenuConstants.FRAME_NO && !MenuConstants.TYPE_DIR.equals(menu.getMenuType())) {
            routerName = StringUtil.isEmpty(menu.getMenuName()) ?
                    MenuConstants.DEFAULT_MENU_NAME + menu.getId() : menu.getMenuName();
        }
        return routerName;
    }

    /**
     * 获取路由地址
     */
    private String getRouterPath(SysMenu menu) {
        if (menu == null || StringUtil.isEmpty(menu.getPath())) {
            return "";
        }

        // 一级目录（类型为目录的顶级菜单）
        if (menu.getParentId().equals(MenuConstants.ROOT_MENU_ID)) {
            return "/" + menu.getPath();
        }
        return menu.getPath();
    }

    /**
     * 获取组件信息
     */
    private String getComponent(SysMenu menu) {
        if (menu == null) {
            return MenuConstants.LAYOUT;
        }

        String component = MenuConstants.LAYOUT;
        // 非目录且非外链
        if (!MenuConstants.TYPE_DIR.equals(menu.getMenuType()) && menu.getIsFrame() == MenuConstants.FRAME_NO) {
            component = StringUtil.isEmpty(menu.getComponent()) ?
                    MenuConstants.INNER_LINK : menu.getComponent();
        }
        return component;
    }

    /**
     * 获取子菜单列表
     */
    private List<SysMenu> getChildMenus(SysMenu parent, List<SysMenu> menus) {
        // 添加空检查，如果父菜单ID为空则返回空列表
        if (parent == null || parent.getId() == null || menus == null) {
            return new ArrayList<>();
        }

        // 添加过滤，确保只处理有效菜单
        return menus.stream()
                .filter(Objects::nonNull) // 过滤null菜单
                .filter(m -> m.getParentId() != null && parent.getId().equals(m.getParentId()))
                .sorted(Comparator.comparing(
                        m -> m.getOrderNum() != null ? m.getOrderNum() : Integer.MAX_VALUE
                ))
                .collect(Collectors.toList());
    }
}